home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / mutt / cmode.mut < prev    next >
Text File  |  1988-10-10  |  11KB  |  375 lines

  1. ;; cmode.mut : an electric C mode
  2.  
  3. ;;   Electric C mode is designed to help keep your C code formatted "as you
  4. ;; code".  You don't have to remember anything special - as you type, what
  5. ;; you type is looked at and may trigger certain actions.  This is a
  6. ;; minimalist C mode ment to enable you to keep your C code formatted in a
  7. ;; consistant manner.  The only extensive help is for comments.
  8.  
  9. ;; Characters that trigger formatting:
  10. ;;  "{": When a "{" is pressed, the following will happen:
  11. ;;     - If the space bar is pressed, "{ }" is generated and the cursor is
  12. ;;     put between the braces.
  13. ;;     - If Enter is pressed:
  14. ;;       And the rest of the line is blank, you will get something like:
  15. ;;        if (a) {        or  if (a)
  16. ;;          cursor        {
  17. ;;        }              cursor
  18. ;;                }
  19. ;;       depending on where the "{" was.  The cursor is indented by the
  20. ;;       amount specified by "indent-level".
  21. ;;     If the rest of the line was not blank, a newline-and-indent is
  22. ;;       done and the text after the { is indented.
  23. ;;       For example:
  24. ;;        if (a) foo(): if a "{ Enter" is done before the foo()
  25. ;;        you will get:
  26. ;;        if (a) {
  27. ;;          foo()
  28. ;;     - Otherwise, a "{" is inserted.
  29. ;;  Backspace:  Behaves like backspacing over spaces even when backspacing
  30. ;;    over tabs.
  31. ;;  Newline (control-J):  Used to give some white space after a variable
  32. ;;    declaration block.  The cursor is left at the same column as the start
  33. ;;    of the declarations.
  34. ;;    int j;    => int j;
  35. ;;           blank line
  36. ;;           cursor
  37. ;;  "/": Comment assistance.
  38. ;;     - If "*" is pressed and the rest of the line is blank and there is
  39. ;;     text to the left of the "/", "/* */" is generated and the cursor
  40. ;;     is put in the middle of the comment.  This is for end of line
  41. ;;     comments like:  if (a) foobar();    /* comment */
  42. ;;     - If "*" is pressed and the entire line is blank, block comment mode
  43. ;;     is entered.  In this mode, your comment will autowrap at the
  44. ;;     comment-wrap-column.  When you hit Enter or autowrap, stars are
  45. ;;     put in the proper place, whitespace is added to match the
  46. ;;     previous comment line.  If you press Enter "/", comment mode will
  47. ;;     terminate.  "*/" or "*" blanks "/" will also terminate comment
  48. ;;     mode.  If you want to get out of comment mode without using the
  49. ;;     above, execute "nocomment".
  50. ;;     Examples:
  51. ;;        /*
  52. ;;             * Comment
  53. ;;         *   Indented a bit
  54. ;;         *   Next line follows the indent.
  55. ;;         */
  56. ;;        /*
  57. ;;        ** Another comment style
  58. ;;        */
  59. ;;     - Otherwise, a "/" is inserted.
  60. ;;  Meta-J:  Format a C block comment.
  61. ;;    If you munge a block comment and want to set it right, use this.
  62. ;;    This formats all the lines between the dot and mark inclusive.
  63. ;;    Put the region around the comment (or the part of the comment you want
  64. ;;      to format) and press M-J.  The comment is commented in the format of
  65. ;;      comment mode.
  66. ;;    Notes:
  67. ;;    To make sure that line breaks are preserved, insert blank lines at
  68. ;;      the breaks.  The blank lines will be deleted after the comment
  69. ;;      is formatted.
  70. ;;    To change the indent level of the block, indent the first line of
  71. ;;      the region to where you want.
  72. ;;  Control-U Meta-J: Format a C boxed comment.
  73. ;;    Same as format block comment except the comment is boxed:
  74. ;;    /********************************
  75. ;;     *   Comment            *
  76. ;;     ********************************/
  77. ;;  You can convert between boxed and block comments by just reformatting.
  78.  
  79. ;; C Durland
  80.  
  81.  
  82. (const
  83.   indent-level 2
  84.   comment-wrap-column 76
  85.  
  86.   C-stars " *"    ; comment body stars: " *"  or "**".
  87.   comet   " */"    ; comment end stars:  " */" or "*/".
  88.  
  89.     ; number of blank lines before and after text in boxed comment
  90.   boxed-comment-space    1
  91.   boxed-comment-trailing-blanks 1    ; blanks between text and *
  92.   boxed-comment-edge-stars "*"        ; right edge stars: "*" or "**"
  93.  
  94.   Enter-key-action "newline-and-indent"
  95. )
  96.  
  97. (defun
  98.   c-mode    ; set up electric C mode
  99.   {
  100.     (tab-stops 0)(word-wrap 0)
  101.     (bind-local-key Enter-key-action    "C-M")
  102.     (bind-local-key "C-mode-{"        "{")
  103.     (bind-local-key "after-declare"    "^J")
  104.     (bind-local-key "Dr.commento"    "/")
  105.     (bind-local-key "BS-untabify"    "^H")
  106.     (bind-local-key "format-C-comment"    "M-J")
  107.   }
  108. )
  109.  
  110. (include me.h)
  111. (include bs_untab.mut)
  112.  
  113. (defun
  114.   "C-mode-{"    ; handle {
  115.   {
  116.     (int key n)
  117.  
  118.     (insert-text "{")(update)
  119.     (switch (key (get-key))
  120.       Space-bar        ;  try for { . } else just insert a blank
  121.     {
  122.       (if (looking-at '\ *$')    ; only whitespace 'til end of line
  123.         { (insert-text "  }")(previous-character)(previous-character) }
  124.         (insert-text " ")
  125.       )
  126.     }
  127.       Enter-key
  128.         {
  129.       (newline-and-indent)(n (current-column))
  130.       (if (looking-at '\ *$')    ; white space to end of line
  131.       {
  132.         (insert-text "}")
  133.         (beginning-of-line)(open-line)
  134.       })
  135.       (to-col (+ n indent-level))
  136.     }
  137.       default (exe-key key)
  138.     )
  139.   }
  140.   after-declare        ; properly indent after a var declare
  141.   {
  142.     (newline-and-indent)(beginning-of-line)(open-line)
  143.     (forward-line 1)(end-of-line)
  144.   }
  145. )
  146.  
  147. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  148. ;;;;;;;;;;;;; Comment mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  149. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  150.  
  151. (defun
  152.   Dr.commento        ; handle "/" & start up comment mode if need be
  153.   {
  154.     (int key col)
  155.  
  156.     (insert-text "/")(update)
  157.     ; Check to see if starting a comment.  No "*" => no comment
  158.     (if (!= (key (get-key)) 0x2A) { (exe-key key)(done) } )
  159.     ; check to see if this is a comment block
  160.     (insert-text "*")
  161.     (col (current-column))(beginning-of-line)
  162.     (if (not (looking-at '\ */\*\ *$'))    ; ws/*ws
  163.     {    ; its not a comment block - give them "/*   */"
  164.       (current-column col)
  165.       (if (looking-at '\ *$')    ; only if at end of line
  166.     { (insert-text "  */")(arg-prefix 3)(previous-character) } )
  167.       (done)
  168.     })
  169.     ; turn on block comment mode
  170.     (current-column col)(buffer-var comment-offset (- col 2))
  171.     (word-wrap comment-wrap-column)
  172.     (bind-local-key "Dr.CR" "C-M")
  173.     (bind-local-key "C-mode-/" "/")
  174.     (insert-text " ")
  175.     (msg "Consulting Dr. Commento")
  176.   }
  177.   nocomment                ; Turn off comment mode
  178.   {
  179.     (bind-local-key Enter-key-action "C-M")
  180.     (bind-local-key "Dr.commento" "/")
  181.     (word-wrap 0)
  182.     (msg "end comment")
  183.   }
  184.   Dr.CR                ; handle Enter while in comment mode
  185.   {
  186.     (int key)
  187.  
  188. (msg "Still consulting Dr. Commento")
  189.     (open-line)(beginning-of-line)
  190.     (if (looking-at '\ *.\ *\*+\(\ *\)') ; [ws]/*[ws] | ws*[*...][ws]
  191.     {
  192.       (forward-line 1)
  193.       (to-col (buffer-var comment-offset))
  194.       (insert-text C-stars (get-matched '\1'))
  195.     })
  196.   }
  197.   C-mode-/            ; handle "/" in comment mode
  198.   {
  199.     (int col)
  200.  
  201.     (col (current-column))
  202.     (previous-character)
  203.     (if (looking-at '\*')    ; "*/" => ending comment
  204.       { (nocomment)(goto ick) })
  205.     (beginning-of-line)
  206.     (if (looking-at '\ *\*+\ *$')    ; [ws]*[*...][ws]/
  207.     {
  208.       (current-column (buffer-var comment-offset))
  209.       (kill-line)
  210.       (insert-text comet)
  211.       (nocomment)
  212.       (done)
  213.     })
  214.   (label ick)
  215.     (current-column col)(insert-text "/")
  216.   }
  217. )
  218.  
  219. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  220. ;;;;;;;; Format block comment ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  221. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  222.  
  223. (defun
  224.   add-stars(int n) HIDDEN
  225.   {
  226.     (int j)
  227.  
  228.     (j (+ n 1))
  229.     (while (!= 0 (-= j 1)) (insert-text "*"))
  230.   }
  231.   format-C-comment
  232.   {
  233.     (bool start-comment end-comment boxed-comment)
  234.     (int offset j)
  235.     (string code-buffer 50)
  236.  
  237.     (boxed-comment (arg-flag))
  238.  
  239.     (start-comment (end-comment FALSE))
  240.  
  241.     (code-buffer (buffer-name -1))
  242.     (delete-region-as-block)
  243.  
  244.     (switch-to-buffer scratch-buffer)
  245.     (buffer-flags -1 BFGone)(clear-buffer -1)
  246.     (insert-register 0)
  247.  
  248.     (beginning-of-buffer)
  249.     (if (re-search-forward '^\ */\*')    ; ^[ws]/*
  250.       {
  251.     (start-comment TRUE)
  252.     (offset (- (current-column) 2))
  253.     (beginning-of-line)
  254.     (re-query-replace '^\ */\*+' "")  ; get rid of ^[ws]/*[*...]
  255.       }
  256.       {
  257.     (if (search-forward C-stars)
  258.       (offset (- (current-column) 2))
  259.       {
  260.         ; else get the block offset from left margin
  261.         (beginning-of-line)
  262.         (while (isspace) (next-character))
  263.         (offset (current-column))
  264.       }
  265.     )
  266.       }
  267.     )
  268.  
  269.     (beginning-of-buffer)
  270.     (if (re-search-forward '\*/\ *$')    ; */[ws]$
  271.     {
  272.       (end-comment TRUE)
  273.       (beginning-of-line)
  274.       (re-query-replace '\ *\*+/\ *$' "")    ; get rid of [ws]*[*...]/[ws]$
  275.     })
  276.     (beginning-of-buffer)
  277.     (re-query-replace '^\ *\*+' "")    ; get rid of [white-space]*[*...]
  278.  
  279.     (beginning-of-buffer)
  280.     (re-query-replace '\ *\*+$' "")    ; get rid of [white-space]*[*...]$
  281.  
  282.     (msg "Formatting comment ...")
  283.     (beginning-of-buffer)
  284.     (adjust-lines
  285.       10000
  286.       (- comment-wrap-column offset 1
  287.     (if boxed-comment
  288.       (+ (strlen boxed-comment-edge-stars) boxed-comment-trailing-blanks)
  289.       0
  290.     ))
  291.       FALSE
  292.     )
  293.     (beginning-of-buffer)
  294.     
  295.     ; put /*, * and */ in front of text
  296.     (if start-comment
  297.     {
  298.       (to-col offset)(insert-text '/*')
  299.       (if boxed-comment
  300.       {
  301.     (if (not (looking-at '\ *$')) (open-line))
  302.     (add-stars (- comment-wrap-column (current-column)))
  303.     (insert-text boxed-comment-edge-stars)
  304.     (j boxed-comment-space)
  305.     (while (<= 0 (-= j 1))
  306.     {
  307.       (newline-and-indent)(insert-text C-stars)
  308.       (to-col comment-wrap-column)(insert-text boxed-comment-edge-stars)
  309.     })
  310.       })
  311.       (forward-line 1)
  312.     })
  313.     (while (not (EoB))
  314.     {
  315.       (if (looking-at '^$')
  316.         { (arg-prefix 1)(kill-line)(continue) }        ; remove blank lines
  317.     {        ; else prepend *
  318.       (to-col offset)(insert-text C-stars)
  319.       (if boxed-comment
  320.           {
  321.         (end-of-line) (to-col comment-wrap-column)
  322.         (insert-text boxed-comment-edge-stars)
  323.       })
  324.     }
  325.       )
  326.       (forward-line 1)
  327.     })
  328.     (if end-comment
  329.     {
  330.       (to-col offset)
  331.       (if boxed-comment
  332.     {
  333.       (j boxed-comment-space)
  334.       (while (<= 0 (-= j 1))
  335.       {
  336.         (insert-text C-stars)
  337.         (to-col comment-wrap-column)(insert-text boxed-comment-edge-stars)
  338.         (newline)(to-col offset)
  339.       })
  340.       (insert-text C-stars)
  341.       (add-stars (- comment-wrap-column (current-column)))
  342.       (insert-text boxed-comment-edge-stars "/")
  343.     }
  344.     (insert-text comet)
  345.       )
  346.     })
  347.  
  348.     ; replace comment
  349.     (beginning-of-buffer)(set-mark)(end-of-buffer)
  350.     (clear-register 0)(append-to-register 0)
  351.  
  352.     (msg "Comment formatted.")
  353.  
  354.     (switch-to-buffer code-buffer)
  355.     (exchange-dot-and-mark)    ; in case buffer was displayed more than once
  356.     (insert-register 0)
  357.  
  358.     ; clean up
  359.     (clear-buffer (attached-buffer scratch-buffer))
  360.   }
  361. )
  362.  
  363. (defun
  364.   delete-region-as-block HIDDEN
  365.   {
  366.     (byte type)(int left-edge width height)(INT size)
  367.  
  368.     (region-stats (loc type))
  369.  
  370.     (if (== type MARK-ABOVE-DOT)(exchange-dot-and-mark))
  371.     (beginning-of-line)
  372.     (arg-prefix height)(kill-line)
  373.   }
  374. )
  375.